package com.yfbao.horizon.demo;

import cn.hutool.core.io.FileUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 分析缓存统计的数据
 */
public class LogCacheStateFileAnalysis {

//    private static String path = "C:\\Users\\byf78\\Desktop\\日志分析\\test\\user-命中";
    private static String path="C:\\Users\\byf78\\Desktop\\日志分析\\性能接口";
    private static String prefix = "ctp-user-info";

//    private static String path = "C:\\Users\\byf78\\Desktop\\日志分析\\test\\命中统计";
//    private static String prefix = "organization-info";

    public static void main(String[] args) {
        doTask("move-key");
        doLiveTask("live-key");
        getFifterFile("命中率");
        List<String> list = listFiles(path, "ctp-user-info.log");
//        getBigKeyFifterLog("-key:");
    }

    public static void getBigKeyFifterLog(String fifter){
        List<String> fileList = listFiles(path, prefix);
        List<String> list = fifterLogs(fileList, fifter);
        String outFile = path+File.separator+"cache-bigkey.log";
        String outFile2 = path+File.separator+"cache-bigkeySET.log";

        Set<String> bigkeyList = new HashSet<>();
        Set<String> bigkeySet = new HashSet<>();
        Set<String> keys = new HashSet<>();
        Set<String> keys2 = new HashSet<>();
        for (String str : list) {
            if(!str.contains(";")){
                continue;
            }
            String[] split = str.split(";");
            for (String keyInfo : split) {
                if(keyInfo.contains("move-key:")){
                    String[] split1 = keyInfo.split("move-key:");
                    keyInfo = split1[1];
                }
                if(keyInfo.contains("live-key:")){
                    String[] split1 = keyInfo.split("live-key:");
                    keyInfo = split1[1];
                }
                String[] split1 = keyInfo.split(":");
                int length = split1.length;
                String lastValue = split1[length - 1];
                try {
                    Long aLong = Long.valueOf(lastValue);
                    if(aLong>10*1024){
                        String key= split1[0];
                        String key2 =split1[0];
                        for(int i=1;i<split1.length-3;i++){
                            key=key+":"+split1[i];
                        }
                        if(!keys.contains(key)){
                            keys.add(key);
                            keyInfo = keyInfo+":"+ (aLong/(1*1024))+"kB";
                            bigkeyList.add(keyInfo);
                        }
                        for(int i=1;i<split1.length-4;i++){
                            key2=key2+":"+split1[i];
                        }
                        if(!keys2.contains(key2)){
                            keys2.add(key2);
                            key2 = key2+":"+ (aLong/(1*1024))+"kB";
                            bigkeySet.add(key2);
                        }
                    }
                }catch (Throwable t){
                    continue;
                }
            }
            if(bigkeyList.size()>1000){
                FileUtil.writeLines(bigkeyList,outFile,"utf-8");
                bigkeyList.clear();
            }
        }
        if(bigkeyList.size()>0){
            FileUtil.writeLines(bigkeyList,outFile,"utf-8");
        }
        FileUtil.writeLines(bigkeySet,outFile2,"utf-8");
//        FileUtil.writeLines(list,outFile,"utf-8");
    }

    private static void doTask(String fifter) {
//        String fifter = "moveCache";
        String outFile = path+File.separator+fifter+".txt";
        List<String> fileList = listFiles(path, prefix);
        List<String> list = fifterLogs(fileList, fifter);
//        List<String> list = fifterLog(file, fifter);
        Map<String, Map<String, CacheStat>> stringCacheStatMap = analysisLog(list,fifter);
        Set<String> set = stringCacheStatMap.keySet();
        List<String> resList = new ArrayList<>();
        Map<String, CacheTotalStat> map = new HashMap<>();
        for (String key : set) {
            Map<String, CacheStat> stringCacheStatMap1 = stringCacheStatMap.get(key);
            Set<String> set1 = stringCacheStatMap1.keySet();
            Integer totalTimes = 0;
            Integer totalLiveTimes = 0;
            for (String cacheKey : set1) {
                CacheStat cacheStat = stringCacheStatMap1.get(cacheKey);
                String str = "key:" + key + ",cacheKey:"+cacheKey+"," + cacheStat.toString();
                System.out.println(str);
                resList.add(str);
                totalTimes =totalTimes+cacheStat.getTimes();
                totalLiveTimes =totalLiveTimes+cacheStat.getLiveTimes();
            }
            CacheTotalStat cacheTotalStat = new CacheTotalStat();
            cacheTotalStat.setCacheNum(set1.size());
            cacheTotalStat.setTotalLiveTimes(totalLiveTimes);
            cacheTotalStat.setTotalTimes(totalTimes);
            map.put(key,cacheTotalStat);
        }
        writeFile(outFile,resList);
        resList.clear();
        resList.add("\n\n");
        resList.add("---------------------统计数据-----------------------------");
        for (String key : map.keySet()) {
            CacheTotalStat cacheTotalStat = map.get(key);
            resList.add(key+":"+cacheTotalStat.toString());
        }
        appendWriteFile(outFile,resList);
    }



    private static List<String> listFiles (String path,String prefix){
        List<String> list = FileUtil.listFileNames(path);
        System.out.println(list);
        if(StringUtils.isBlank(prefix)){
            return list;
        }
        List<String> collect = list.stream().filter(str -> str.startsWith(prefix)).collect(Collectors.toList());
        return collect;
    }

    private static void doLiveTask(String fifter) {
//        String fifter = "moveCache";
        String outFile = path+File.separator+fifter+".txt";
        List<String> fileList = listFiles(path, prefix);
        List<String> list = fifterLogs(fileList, fifter);
//        List<String> list = fifterLog(file, fifter);


        Map<String, Map<String, CacheStat>> stringCacheStatMap = analysisDateLog(list,fifter);
        Set<String> set = stringCacheStatMap.keySet();
        List<String> resList = new ArrayList<>();
        Map<String, CacheTotalStat> map = new HashMap<>();
        for (String key : set) {
            Map<String, CacheStat> stringCacheStatMap1 = stringCacheStatMap.get(key);
            Set<String> set1 = stringCacheStatMap1.keySet();
            Integer totalTimes = 0;
            Integer totalLiveTimes = 0;
            for (String cacheKey : set1) {
                CacheStat cacheStat = stringCacheStatMap1.get(cacheKey);
                String str = "key:" + key + ",cacheKey:"+cacheKey+"," + cacheStat.toString();
                System.out.println(str);
                resList.add(str);
                totalTimes =totalTimes+cacheStat.getTimes();
                totalLiveTimes =totalLiveTimes+cacheStat.getLiveTimes();
            }
            CacheTotalStat cacheTotalStat = new CacheTotalStat();
            cacheTotalStat.setCacheNum(set1.size());
            cacheTotalStat.setTotalLiveTimes(totalLiveTimes);
            cacheTotalStat.setTotalTimes(totalTimes);
            map.put(key,cacheTotalStat);
        }
        writeFile(outFile,resList);

        resList.clear();
        resList.add("\n\n");
        resList.add("---------------------统计数据-----------------------------");
        for (String key : map.keySet()) {
            CacheTotalStat cacheTotalStat = map.get(key);
            resList.add(key+":"+cacheTotalStat.toString());
        }
        appendWriteFile(outFile,resList);
    }

    private static void getFifterFile(String fifter){
//        String file = "C:\\Users\\byf78\\Desktop\\日志分析\\test\\organization-info.log.2023-07-20.4";
        List<String> fileList = listFiles(path, prefix);
//        String fifter = "moveCache";
        String outFile = path+File.separator+fifter+".txt";
        for (String s : fileList) {
            String file = path+File.separator+s;
            List<String> list = fifterLog(file, fifter);
            List<String> collect = new ArrayList<>();
            for (String s1 : list) {
//                String[] split = s1.split("CacheStats");
                String[] split = s1.split(fifter);
                collect.add(split[1]);
            }
//            List<String> collect = list.stream().map(str -> str.split("||||")[1]).collect(Collectors.toList());
            if(!collect.isEmpty()){
                writeFile(outFile,collect,true);
            }
        }
    }

    private static List<String> fifterLogs(List<String> files, String fifterStr) {
        List<String> list = new ArrayList<>();
        for (String file : files) {
            if(!file.startsWith(path)){
                file = path+File.separator+file;
            }
            List<String> list1 = fifterLog(file, fifterStr);
            list.addAll(list1);
        }
        return list;
    }

    private static List<String> fifterLog(String file, String fifterStr) {
        List<String> list = FileUtil.readLines(new File(file), Charset.forName("utf-8"));
        if (list == null || list.isEmpty()) {
            return Collections.EMPTY_LIST;
        }

        List<String> collect = list.stream().filter((str) -> str.contains(fifterStr)).collect(Collectors.toList());
        System.out.println("size:" + collect.size());
        return collect;
    }

    private static Map<String, Map<String, CacheStat>> analysisLog(List<String> list,String sub) {
        String subStr = sub;
        List<String> collect = list.stream().map(str -> str.substring(str.indexOf(subStr))).collect(Collectors.toList());
        Map<String, Map<String, CacheStat>> map = new HashMap<>();
        int errorNum = 0;
        for (String s : collect) {
            String[] split = s.split(";");
            for (String s1 : split) {
                String[] split1 = s1.split(":");
                if (split1.length < 8 && split1.length != 4) {
                    System.out.println("length error:" + s1);
                    continue;
                }
                String key=null;
                String cacheKey =null;
                Integer time=0;
                Integer liveTimes =0;
                try {
                    if (split1.length == 9) {
                        key = split1[4];
                        cacheKey = split1[6];
                        time = Integer.valueOf(split1[7]);
                        int length = split1[8].length();
                        liveTimes = Integer.valueOf(split1[8].substring(0, length - 1));
                    }else if (split1.length>9){
                        key = split1[5] ;
                        cacheKey =  split1[7];
                        time = Integer.valueOf(split1[8]);
                        int length = split1[9].length();
                        liveTimes = Integer.valueOf(split1[9].substring(0, length - 1));
                    }else if (split1.length == 8){
                        key = split1[5];
                        cacheKey = split1[7];
                        time = Integer.valueOf(split1[8]);
                        int length = split1[8].length();
                        liveTimes = Integer.valueOf(split1[8].substring(0, length - 1));
                    }
                    else if (split1.length == 4){
                        key = split1[1];
                        cacheKey = split1[1];
                        time = Integer.valueOf(split1[2]);
                        int length = split1[3].length();
                        liveTimes = Integer.valueOf(split1[3].substring(0, length - 1));
                    }
                }catch (Exception e){
                    errorNum++;
                    System.out.println("error s1 "+errorNum+":"+s1);

                    continue;
//                    if(errorNum>5){
//                        System.out.println(e);
//                        return new HashMap<>();
//                    }
                }

                Map<String, CacheStat> cacheMap = map.get(key);
                if (cacheMap == null) {
                    cacheMap = new HashMap<>();
                    map.put(key, cacheMap);
                }
                CacheStat cacheStat = cacheMap.get(cacheKey);
                if (cacheStat == null) {
                    cacheStat = new CacheStat();
                    cacheMap.put(cacheKey, cacheStat);
                    cacheStat.setTimes(time);
                    cacheStat.setLiveTimes(liveTimes);
                } else {
                    cacheStat.setTimes(cacheStat.getTimes() + time);
                    cacheStat.setLiveTimes(cacheStat.getLiveTimes() + liveTimes);
                }
            }
        }
        System.out.println("map size:" + map.size());
        return map;
    }

    private static Map<String, Map<String, CacheStat>> analysisDateLog(List<String> list,String sub) {
        String subStr = sub;
        List<String> collect = list.stream().map(str -> str.substring(str.indexOf(subStr))).collect(Collectors.toList());
        Map<String, Map<String, CacheStat>> map = new HashMap<>();
        int errorNum = 0;
        for (String s : collect) {
            String[] split = s.split(";");
            for (String s1 : split) {
                String[] split1 = s1.split(":");
                if (split1.length < 8) {
                    System.out.println("length error:" + s1);
                    continue;
                }
                String key=null;
                String cacheKey =null;
                Integer time=0;
                Integer liveTimes =0;
                try {
                    if (split1.length == 9) {
                        key = split1[4];
                        cacheKey = split1[6];
                        time = Integer.valueOf(split1[7]);
                        int length = split1[8].length();
                        liveTimes = Integer.valueOf(split1[8].substring(0, length - 1));
                    }else if(split1.length>9){
                        key = split1[5] ;
                        cacheKey =  split1[7];
                        time = Integer.valueOf(split1[8]);
                        int length = split1[9].length();
                        liveTimes = Integer.valueOf(split1[9].substring(0, length - 1));
                    }else if(split1.length ==8){
                        key = split1[4] ;
                        cacheKey =  split1[6];
                        time = Integer.valueOf(split1[7]);
                        int length = split1[8].length();
                        liveTimes = Integer.valueOf(split1[8].substring(0, length - 1));
                    }
                }catch (Exception e){
                    errorNum++;
                    System.out.println("error live s1 "+errorNum+":"+s1);
                    System.out.println(e);
                    continue;
//                    return new HashMap<>();
                }
                Map<String, CacheStat> cacheMap = map.get(key);
                if (cacheMap == null) {
                    cacheMap = new HashMap<>();
                    map.put(key, cacheMap);
                }
                CacheStat cacheStat = cacheMap.get(cacheKey);
                if (cacheStat == null) {
                    cacheStat = new CacheStat();
                    cacheMap.put(cacheKey, cacheStat);
                    cacheStat.setTimes(time);
                    cacheStat.setLiveTimes(liveTimes);
                } else {
                    cacheStat.setTimes(cacheStat.getTimes() + time);
                    cacheStat.setLiveTimes(cacheStat.getLiveTimes() + liveTimes);
                }
            }
        }
        System.out.println("map size:" + map.size());
        return map;
    }

    private static void writeFile(String file, List<String> list,Boolean isAppend) {
        FileUtil.writeLines(list, file, "utf-8",isAppend);
    }

    private static void writeFile(String file, List<String> list) {
        FileUtil.writeLines(list, file, "utf-8");
    }

    private static void appendWriteFile(String file, List<String> list) {
        FileUtil.appendLines(list, file, "utf-8");
    }

    static class CacheStat {
        public Integer getTimes() {
            return times;
        }

        public void setTimes(Integer times) {
            this.times = times;
        }

        public Integer getLiveTimes() {
            return liveTimes;
        }

        public void setLiveTimes(Integer liveTimes) {
            this.liveTimes = liveTimes;
        }

        private Integer times;
        private Integer liveTimes;


        public String toString() {
            return times + "," + liveTimes;
        }
    }

    static class CacheTotalStat{
        public Integer getTotalTimes() {
            return totalTimes;
        }

        public void setTotalTimes(Integer totalTimes) {
            this.totalTimes = totalTimes;
        }

        public Integer getTotalLiveTimes() {
            return totalLiveTimes;
        }

        public void setTotalLiveTimes(Integer totalLiveTimes) {
            this.totalLiveTimes = totalLiveTimes;
        }

        private Integer  totalTimes;
        private Integer totalLiveTimes;

        public Integer getCacheNum() {
            return cacheNum;
        }
        public String toString() {
            return "累计总数:"+cacheNum + ",累计命中：" +totalTimes+",累计保存时长："+ totalLiveTimes;
        }

        public void setCacheNum(Integer cacheNum) {
            this.cacheNum = cacheNum;
        }

        private Integer  cacheNum;
    }
}
